home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource5
/
314_01
/
mnpintrf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-16
|
11KB
|
503 lines
/*==========================================================================
The Microcom MNP Library
(Microsoft C Version)
----------------------------------------------------------------------------
MNPINTRF - MNP Link Interface Routines
----------------------------------------------------------------------------
Modification History
3/30/87 - Compuserve V1.0
==========================================================================*/
/* Header files
*/
#include <dos.h>
#include <mnpdat.h>
/* Local definitions
*/
#define NOWAIT 0
#define BIT3SET(bit) (lcb.status_3 & bit)
#define BIT1SET(bit) (lcb.status_1 & bit)
#define SETBIT1(bit) lcb.status_1 |= bit;
#define SETBIT3(bit) lcb.status_3 |= bit;
USIGN_8 get_sbuf();
void mnpdisconnect();
SIGN_16 ia_send();
/* Link status block
*/
struct link_stat_blk
{
USIGN_16 p_status;
USIGN_16 l_status;
USIGN_16 s_count;
USIGN_16 r_count;
USIGN_16 all_sent;
};
/* External references
*/
extern struct BUFFER ftb;
extern struct link_ctl_blk lcb; /* link control block */
extern struct TIMERS tmr;
extern USIGN_16 sf_busy, /* 'send framer busy' flag */
sf_lt, /* 'LT in progress' flag */
sf_len, /* send framer length */
tbcnt; /* unacked transmit buf count */
extern USIGN_8 chan_no; /* hardware channel no. */
/* Data declarations
*/
struct MNP_CB mnpcb; /* MNP control block */
USIGN_8 rbuf[RBUF_LEN]; /* receive buffer */
USIGN_8 *rb_iptr, /* rcv insert ptr */
*rb_rptr; /* rcv remove ptrs */
USIGN_16 rb_cnt; /* rcv count */
USIGN_8 sbuf[SBUF_LEN]; /* send buffer */
USIGN_8 *sb_iptr, /* snd insert ptr */
*sb_rptr; /* snd remove ptr */
USIGN_16 sb_cnt; /* snd count */
USIGN_8 *iatbiptr; /* rcv temp insert ptr */
struct BLST *iatb_struct; /* transmit buffers */
USIGN_8 baudrate; /* line speed */
/*GLOBAL***********************************************************************
mnpconnect - establish an MNP link-connection
synopsis: retcode = mnpconnect(rate,format,port,mode);
input: int rate, physical-connection speed
format, character format
port, comm port
mode; originator/answerer
output: int retcode; establishment result
**************************************************************************/
SIGN_16 mnpconnect(rate,format,port,mode)
USIGN_16 rate,
format,
port,
mode;
{
/* Initialize send, receive counts and buffer pointers.
*/
rb_cnt = sb_cnt = 0;
rb_iptr = rb_rptr = rbuf;
sb_iptr = sb_rptr = sbuf;
/* Initialize physical-connection variables
*/
baudrate = rate;
chan_no = port-1;
mnpcb.parity = format;
/* Attempt link establishment and exit. as_connect return code is
** returned as function value.
*/
return(as_connect(&mnpcb,mode));
}
/*GLOBAL***********************************************************************
mnpdisconnect - terminate an MNP link-connection
synopsis: mnpdisconnect();
input: none
output: none
******************************************************************************/
void mnpdisconnect()
{
/* Just call mnpllvl routine, signalling link-user initiated termination.
*/
as_disconnect(255,0);
}
/*GLOBAL***********************************************************************
mnpreceive - receive data on an MNP link-connection
synopsis: retcode = mnpreceive(&buffer,buflen);
input: unsigned char *buffer; pointer to user buffer
int buflen; length of user buffer
output: int retcode; if positive, the number of data bytes
copied into the user data buffer;
if negative, link error code
******************************************************************************/
SIGN_16 mnpreceive(bufptr,buflen)
USIGN_8 *bufptr;
USIGN_16 buflen;
{
SIGN_16 retcode;
register USIGN_16 count;
register USIGN_8 c;
/* Maintain the link-connection. On link error, return with the
** error code as the function value.
*/
if (retcode = as_link())
return(retcode);
if (retcode = ia_send(&mnpcb))
return(retcode);
/* Initialize
*/
count = 0;
/* If there is receive data, copy as much as possible into the
** user's buffer. Note that if a 7-bit character format has been
** selected for the link, then the high-order bit of the data octet
** is set to 0.
*/
while ((rb_cnt > 0) && (buflen > 0))
{
buflen--;
count++;
rb_cnt--;
c = *rb_rptr++;
if (mnpcb.parity) c &= 0x7f;
*bufptr++ = c;
if (rb_rptr >= (rbuf + RBUF_LEN))
rb_rptr = rbuf;
}
/* Maintain the link-connection. On link error, return with error
** code as function value.
*/
if (retcode = as_link())
return(retcode);
if (retcode = ia_send(&mnpcb))
return (retcode);
/* Exit. Function value is the number of octets moved into the user
** buffer.
*/
return(count);
}
/*GLOBAL***********************************************************************
mnpsend - send data on an MNP link-connection
synposis: retcode = mnpsend(&buffer,buflen);
input: unsigned char *buffer; pointer to user data buffer
int buflen; length of user data buffer
output: int retcode - if positive, the number of data bytes
copied from the user data buffer;
if negative, link error code
***************************************************************************/
SIGN_16 mnpsend(bufptr,buflen)
USIGN_8 *bufptr;
USIGN_16 buflen;
{
SIGN_16 retcode;
register USIGN_16 count;
/* Maintain the link-connection.
*/
if (retcode = as_link())
return(retcode);
/* Initialize
*/
count = 0;
/* Copy as much user data as possible into the send ring buffer.
*/
while ((sb_cnt < SBUF_LEN) && (buflen > 0))
{
count++;
sb_cnt++;
buflen--;
*sb_iptr++ = (unsigned char) setpar(*bufptr++,mnpcb.parity);
if (sb_iptr >= sbuf + SBUF_LEN)
sb_iptr = sbuf;
}
/* Try to send an LT LPDU or continue one in progress and maintain
** the link once again.
*/
if (retcode = ia_send(&mnpcb))
return(retcode);
if (retcode = as_link())
return(retcode);
/* Exit
*/
return(count);
}
/*GLOBAL***********************************************************************
mnpstatus - get link-connection status information
synopsis: mnpstatus(&lstat_blk);
input: struct link_stat_blk *lstat_blk; pointer to status block
output: none
******************************************************************************/
mnpstatus(lsb)
struct link_stat_blk *lsb;
{
/* Maintain the link-connection. Here ignore any link errors as these
** will be reflected in status values.
*/
as_link();
ia_send(&mnpcb);
/* Build link status block.
*/
if (lne_stat())
lsb->p_status = FALSE;
else
lsb->p_status = TRUE;
if (BIT1SET(LINK_EST))
lsb->l_status = TRUE;
else
lsb->l_status = FALSE;
/* Number of bytes free in send buffer. By definition this number is
** the size of the send buffer when the link-connection is not
** established.
*/
if (lsb->l_status == FALSE)
sb_cnt = 0;
lsb->s_count = SBUF_LEN - sb_cnt;
/* Amount of data in receive buffer
*/
lsb->r_count = rb_cnt;
/* Data is 'all sent' if the user send buffer is empty and all data
** messages have been acknowledged.
*/
if ((sb_cnt == 0) && (tbcnt == 0))
lsb->all_sent = TRUE;
else
lsb->all_sent = FALSE;
}
/*GLOBAL********************************************************************
mnpbreak - send a break signal (using MNP attention)
synopsis: retcode = mnpbreak();
input: none
output: int retcode; link error code
***************************************************************************/
SIGN_16 mnpbreak()
{
SIGN_16 retcode;
/* If attention service has not been negotiated for this link-connection,
** return. Function value = attention not supported.
*/
if (lcb.prot_level != 2)
return(-75);
/* Maintain the link. Return link error code if link has failed.
*/
if (retcode = as_link())
return(retcode);
/* If an attention has already been sent and not yet acknowledged, just
** return. Funtion value = attention in progress.
*/
if (BIT3SET(LN_SENT))
return(-76);
/* Ok to send a destructive break using the MNP attention mechanism.
*/
clr_int();
rb_iptr = rb_rptr = rbuf;
sb_iptr = sb_rptr = sbuf;
rb_cnt = sb_cnt = NULL;
SETBIT3(LN_SENT)
link_reset();
dphase_init();
SETBIT3(LN_TIMER)
tmr.ln = lcb.lt_tmr;
++lcb.ln_ssn;
lcb.ln_stype=1;
set_int();
return(lpdu_send(LN,NOWAIT));
}
/*LOCAL------------------------------------------------------------------------
ia_send - build an LT or add data to one in progress
-----------------------------------------------------------------------------*/
SIGN_16 ia_send(mnpcb)
struct MNP_CB *mnpcb;
{
SIGN_16 retcode;
/* Just exit if there is nothing to send.
*/
if (sb_cnt == 0)
return(SUCCESS);
/* Also just return if an attention is in progress.
*/
if (BIT3SET(LN_RECEIVED) || BIT3SET(LN_SENT))
return(SUCCESS);
/* If the send framer is not busy and there is remote credit,
** start an LT LPDU.
*/
clr_int();
if (!sf_busy)
{
set_int();
if (lcb.rem_credit == 0)
return(SUCCESS);
if (get_b(mnpcb->ftb, &iatb_struct) == FAILURE)
return(SUCCESS);
iatb_struct->len = 5;
iatbiptr = iatb_struct->bptr;
*iatbiptr++ = 4;
*iatbiptr++ = LT;
*iatbiptr++ = 1;
*iatbiptr++ = 1;
*iatbiptr++ = ++lcb.lt_ssn;
/* Copy bytes out of the send buffer as long as there are any and there
** is space in the LT LPDU (max is 64 + header of 5 = 69 for Class 3)
*/
while ((iatb_struct->len < 69) && (sb_cnt > 0))
{
iatb_struct->len++;
*iatbiptr++ = get_sbuf();
}
/* Adjust remote credit.
*/
clr_int();
if (--lcb.rem_credit < 0)
lcb.rem_credit = 0;
tbcnt++;
set_int();
/* Now start sending an LT LPDU. Initiate the LT retransmission timer
** if it is not already active.
*/
if (retcode = send_pdu(LT, NOWAIT, iatb_struct))
return(retcode);
sf_lt = 1;
if (!BIT1SET(RET_TIMER))
{
SETBIT1(RET_TIMER)
tmr.lt = lcb.lt_tmr;
}
if (ftb.used == 1)
ftb.used_lst = iatb_struct;
}
/* If the send framer is busy and it is busy with an LT LPDU, try to add
** as much send buffer data as possible to the current LT.
*/
else
{
if (sf_lt == 1)
{
while ((iatb_struct->len < 69) && (sb_cnt > 0))
{
iatb_struct->len++;
sf_len++;
*iatbiptr++ = get_sbuf();
}
}
}
/* Be sure that interrupts are re-enabled.
*/
set_int();
/* Exit
*/
return(SUCCESS);
}
/*LOCAL------------------------------------------------------------------------
get_sbuf - get a data octet from the send buffer
-----------------------------------------------------------------------------*/
USIGN_8 get_sbuf()
{
register USIGN_8 c;
/* Remove an octet from the send buffer and return as function value.
** This routine handles the buffer count and pointer into the circular
** buffer.
*/
sb_cnt--;
c = *sb_rptr++;
if (sb_rptr >= sbuf + SBUF_LEN)
sb_rptr = sbuf;
/* Exit
*/
return(c);
}